<template>
	<div class="app-granted-authorities-tree">
		<a-input-search
			v-model:value="searchValue"
			class="app-granted-authorities-tree__search"
			:disabled="disabled"
			@change="onSearch"
		/>
		<a-tree
			v-model:selectedKeys="selectedKeys"
			v-model:checkedKeys="checkedKeys"
			v-model:expandedKeys="expandedKeys"
			:tree-data="treeData"
			:fieldNames="fieldNames"
			:disabled="disabled"
			checkable
			multiple
			@check="checkBox"
		>
			<template #title="{ display_name }">
				<span>{{ display_name }}</span>
			</template>
		</a-tree>
	</div>
</template>
<script setup lang="ts">
import { deepCopy, IEvent, IParam } from '@/core';
import { Http } from '@/http';
import { PropType, Ref, ref } from 'vue';
interface EditorEmit {
	(name: 'component-action', value: IEvent<string>): void;
}
const props = defineProps({
	controller: { type: Object as PropType<any> },
	name: { type: String },
	disabled: { type: Boolean },
	url: { type: String },
	requestMode: { type: String as PropType<'get' | 'post'>, default: 'post' },
	store: { type: Object as PropType<IParam>, default: () => {} },
});
const emit = defineEmits<EditorEmit>();
const selectedKeys = ref<string[]>([]);
const checkedKeys = ref<string[]>([]);
const expandedKeys = ref<string[]>([]);
const treeData: Ref<IParam[]> = ref([]);
const items: Ref<IParam[]> = ref([]);
const searchValue = ref('');
const fieldNames = { children: 'children', key: 'id', title: 'display_name' };
const loadUrl = () => {
	let tempUrl = props.url;
	if (props.url) {
		const tempStr = props.url.match(/{(.*?)}/g);
		if (tempStr && tempStr.length > 0) {
			const tempValue = tempStr[0].slice(1, -1);
			if (tempValue) {
				const data = props.store?.data;
				if (data) {
					const replaceValue = data[tempValue];
					tempUrl = props.url.replace(/{(.*?)}/g, replaceValue);
				}
			}
		}
	}
	return tempUrl;
};
const onSearch = () => {
	if (searchValue.value == '') {
		treeData.value = items.value;
		return;
	}
	treeData.value = filter(JSON.parse(JSON.stringify(items.value)));
};
const filter = (_items: IParam[]) => {
	const tempArr: IParam[] = [];
	_items.forEach((item: IParam) => {
		const _index = item.display_name.indexOf(searchValue.value);
		if (_index < 0) {
			if (item.children && item.children.length > 0) {
				const tempChildArr: IParam[] = filter(item.children);
				if (tempChildArr && tempChildArr.length > 0) {
					item.children = tempChildArr;
					tempArr.push(item);
					expandedKeys.value.push(item.id);
				}
			}
		} else {
			tempArr.push(item);
		}
	});
	return tempArr;
};
const load = () => {
	const tempUrl = loadUrl();
	if (tempUrl) {
		Http.getHttp()({
			method: props.requestMode,
			url: tempUrl,
		}).then((response: any) => {
			if (!response || !response.success) {
				console.warn('数据加载失败');
			}
			if (response.data) {
				items.value = response.data.permissions;
				treeData.value = response.data.permissions;
				setSelect();
			}
		});
	} else {
		console.warn('无数据加载路径');
	}
};
const checkBox = (checkedKeys: string[], e: IParam) => {
	const tempData: IParam[] = [];
	if (checkedKeys && checkedKeys.length > 0) {
		const allSelectNodes: IParam[] = [];
		const selectNodes: IParam[] = [];
		checkedKeys.forEach((childKey: string) => {
			const nodes: IParam[] = getParentNodeByChildKey(childKey);
			allSelectNodes.push(...nodes);
		});
		allSelectNodes.forEach((node: IParam) => {
			const index = selectNodes.findIndex(
				(select: IParam) => select.id === node.id
			);
			if (index == -1) {
				selectNodes.push(node);
			}
		});
		selectNodes.forEach((select: IParam) => {
			delete select.children;
			tempData.push({
				...select,
				authority: select.id,
				display_name: select.display_name,
				permission_type: select.type,
			});
		});
	}
	emitFun(tempData);
};
const getParentNodeByChildKey = (childKey: string): any[] => {
	let selectNodes: any[] = [];
	if (childKey) {
		const filterNodes = (tree: any[], selectNodes: any[]): boolean => {
			if (!tree.length) return false;
			for (let node of tree) {
				let flg: boolean = false;
				if (node.children && node.children.length > 0) {
					flg = filterNodes(node.children, selectNodes);
				}
				if (flg || Object.is(node.id, childKey)) {
					selectNodes.push(deepCopy(node));
					return true;
				}
			}
			return false;
		};
		filterNodes(items.value, selectNodes);
	}
	return selectNodes;
};
const getTreeNodeByKey = (id: string): any[] => {
	let node: any[] = [];
	if (items.value.length > 0 && id) {
		const getNode = (tree: any[], item: any) => {
			if (!tree.length) return false;
			for (let _node of tree) {
				if (_node.children && _node.children.length > 0) {
					getNode(_node.children, item);
				}
				if (Object.is(_node.id, id)) {
					item.push(deepCopy(_node));
				}
			}
		};
		getNode(items.value, node);
	}
	return node;
};
const emitFun = (data: IParam[]) => {
	emit('component-action', {
		name: 'granted_authorities',
		action: 'valueChange',
		data: data,
	});
};
const setSelect = () => {
	if (props.store.data['granted_authorities']) {
		props.store.data['granted_authorities'].forEach(
			(item: any, index: number) => {
				const id = item.authority;
				const node: any = getTreeNodeByKey(id);
				if (node.length == 1 && !node[0].children) {
					const index = checkedKeys.value.indexOf(id);
					if (index < 0) {
						checkedKeys.value.push(id);
					}
				}
			}
		);
	}
};
watch(
	() => props.store.data,
	(newVal: any, oldVal: any) => {
		if (
			newVal &&
			newVal['deploy_system_id'] &&
			newVal['deploy_system_id'] !== oldVal['deploy_system_id']
		) {
			load();
		} else if (
			newVal &&
			newVal['granted_authorities'] &&
			newVal['granted_authorities'] !== oldVal['granted_authorities']
		) {
			setSelect();
		}
	},
	{
		immediate: true,
		deep: true,
	}
);
</script>
<style lang="less">
.app-granted-authorities-tree {
	.app-granted-authorities-tree__search {
		margin-bottom: 8px;
		padding-right: 8px;
		position: sticky;
		top: 0;
		z-index: 1;
	}
}
</style>
